iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0
Software Development

當rust 遇上 cqrs & es系列 第 12

D12 Query of Reader

  • 分享至 

  • xImage
  •  

今天來試一下Query 用的 Model

先製作查詢使用的模型DTO

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ReaderDto {
    pub id: String,
    pub name: String,
    pub books_borrowed: u32,
    pub next_due_date: Option<DateTime<Utc>>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ReaderBorrowedRecordDto {
    pub book_id: String,
    pub book_name: String,
    pub borrowed_date: DateTime<Utc>,
    pub due_date: DateTime<Utc>,
}

暫時不連實際DB,資料先放Query裡(InMemory:

#[derive(Debug, Default)]
pub struct ReaderQuery {
    pub readers: Arc<Mutex<HashMap<String, ReaderDto>>>,
    pub reader_borrowed_records: Arc<Mutex<Vec<ReaderBorrowedRecordDto>>>,
}

實作 Query trait :

#[async_trait]
impl Query<Reader> for ReaderQuery {
    async fn dispatch(&self, aggregate_id: &str, events: &[EventEnvelope<Reader>]) {
        for event in events {
            match &event.payload {
                ReaderEvent::ReaderCreated { name, id } => {
                    let mut readers = self.readers.lock().unwrap();
                    readers.insert(aggregate_id.to_string(), ReaderDto {
                        id: id.to_string(),
                        name: name.to_string(),
                        ..Default::default()
                    });
                }
                ReaderEvent::BookBorrowed(borrowing) => {
                    let mut readers = self.readers.lock().unwrap();
                    let reader = readers.get_mut(aggregate_id).unwrap();
                    reader.books_borrowed += 1;
                    if reader.next_due_date.is_none() 
                    || reader.next_due_date.unwrap() > borrowing.due_date {
                        reader.next_due_date = Some(borrowing.due_date);
                    }
                }
                ReaderEvent::BookReturned(borrowing) => {
                    let mut readers = self.readers.lock().unwrap();
                    let reader = readers.get_mut(aggregate_id).unwrap();
                    reader.books_borrowed -= 1;
                    if reader.books_borrowed == 0 {
                        reader.next_due_date = None;
                    } else if reader.next_due_date.unwrap() == borrowing.due_date {
                        let mut next_due_date = None;
                        for record in 
                        self.reader_borrowed_records.lock().unwrap().iter() {
                            if record.book_id == borrowing.book_id {
                                continue;
                            }
                            if next_due_date.is_none() 
                            || next_due_date.unwrap() > record.due_date {
                                next_due_date = Some(record.due_date);
                            }
                        }
                        reader.next_due_date = next_due_date;
                    }
                }
            }
        }
    }
}

原本已借閱書籍dto想放書名,不過先前實作的指令及事件不含書名,變成這裡Query傳入時,要利用book_id再去查詢book的資料,不知道這算不算是寫入時需要的查詢,目前還沒想到好的實作方式,也許之後實作DB 可以透過DB的查詢來處理?


上一篇
D11 service testing
下一篇
D13 測試 reader query
系列文
當rust 遇上 cqrs & es30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言